package cn.sh.library.gmwx.utils;

import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by liuyi on 2015/7/6.
 */
public class ExcelExporter {

    private Workbook wb;

    private Sheet activeSheet;

    private Map<String, Sheet> sheetMap = new HashMap<>();

    public ExcelExporter(String filename, String... sheetNames) throws IOException {
        InputStream inputStream = this.getClass().getResourceAsStream("/template/" + filename);
        String extensionName = FilenameUtils.getExtension(filename);
        if ("xls".equalsIgnoreCase(extensionName)) {
            this.wb = new HSSFWorkbook(inputStream);
        } else {
            this.wb = new XSSFWorkbook(inputStream);
        }

        for(String sheetName : sheetNames) {
            if( activeSheet == null) activeSheet = wb.getSheet(sheetName);
            this.sheetMap.put(sheetName, wb.getSheet(sheetName));
        }

        for(int i = wb.getNumberOfSheets() - 1; i >=0 ; i --) {
            Sheet sheet = wb.getSheetAt(i);
            if (!sheetMap.containsKey(sheet.getSheetName())) {
                wb.removeSheetAt(i);
            }
        }
    }

    public void setSheetName(String name){
        if(StringUtils.isNotBlank(name)){
            name = name.replaceAll("[^0-9|^a-z|^A-Z|^\u4e00-\u9fa5]", "");
        }
        if(StringUtils.isBlank(name)){
            name = "sheet_" + wb.getSheetIndex(this.activeSheet);
        }
        this.wb.setSheetName(this.wb.getSheetIndex(this.activeSheet), name);
    }

    public Sheet getActiveSheet(){
        return this.activeSheet;
    }

    public void activeSheet(String sheetName){
        this.activeSheet = sheetMap.get(sheetName);
    }

    public Sheet getSheet(String sheetName){
        return sheetMap.get(sheetName);
    }

    public Workbook getWorkbook(){
        return this.wb;
    }

    public Cell getCell(int rowIndex, int cellNum){
        Row row = this.activeSheet.getRow(rowIndex);
        if( row == null) row = this.activeSheet.createRow(rowIndex);
        Cell cell = row.getCell(cellNum);
        if(cell == null) cell = row.createCell(cellNum);
        return cell;
    }

    /**
     * 设置字符串类型的数据
     *
     * @param rowIndex
     *            --行值
     * @param cellNum
     *            --列值
     * @param value
     *            --字符串类型的数据
     */
    public void setCellStrValue(int rowIndex, int cellNum, String value) {
        getCell(rowIndex, cellNum).setCellValue(value);
    }

    /**
     * 设置日期/时间类型的数据
     *
     * @param rowIndex
     *            --行值
     * @param cellNum
     *            --列值
     * @param value
     *            --日期/时间类型的数据
     */
    public void setCellDateValue(int rowIndex, int cellNum, Date value) {
        getCell(rowIndex, cellNum).setCellValue(value);
    }

    /**
     * 设置浮点类型的数据
     *
     * @param rowIndex
     *            --行值
     * @param cellNum
     *            --列值
     * @param value
     *            --浮点类型的数据
     */
    public void setCellDoubleValue(int rowIndex, int cellNum, double value) {
        getCell(rowIndex, cellNum).setCellValue(value);
    }

    /**
     * 设置Bool类型的数据
     *
     * @param rowIndex
     *            --行值
     * @param cellNum
     *            --列值
     * @param value
     *            --Bool类型的数据
     */
    public void setCellBoolValue(int rowIndex, int cellNum, boolean value) {
        getCell(rowIndex, cellNum).setCellValue(value);
    }

    /**
     * 设置日历类型的数据
     *
     * @param rowIndex
     *            --行值
     * @param cellNum
     *            --列值
     * @param value
     *            --日历类型的数据
     */
    public void setCellCalendarValue(int rowIndex, int cellNum, Calendar value) {
        getCell(rowIndex, cellNum).setCellValue(value);
    }

    /**
     * 设置富文本字符串类型的数据。可以为同一个单元格内的字符串的不同部分设置不同的字体、颜色、下划线
     *
     * @param rowIndex
     *            --行值
     * @param cellNum
     *            --列值
     * @param value
     *            --富文本字符串类型的数据
     */
    public void setCellRichTextStrValue(int rowIndex, int cellNum,
                                        RichTextString value) {
        getCell(rowIndex, cellNum).setCellValue(value);
    }

    public byte[] exportToBytes() throws IOException {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        try {
            wb.write(bos);
            return bos.toByteArray();
        } finally {
            try {
                bos.close();
            } catch (Exception e){}
        }
    }

//    public static void main(String[] args) throws IOException{
//        ExcelImportor importor = new ExcelImportor(Constants.EXPORT_EXCEL_TEMPLATE,
//                Constants.EXPORT_EXCEL_TEMPLATE_INVESTMENT);
//
//        ExcelExtractor extractor = new ExcelExtractor((HSSFWorkbook)importor.getWorkbook());
//        //字符串所包含的类型，详见api
//        extractor.setIncludeSheetNames(true);
//        extractor.setFormulasNotResults(false);
//        extractor.setIncludeCellComments(true);
//        //获得字符串形式
//        String text = extractor.getText();
//        System.out.println(text);
//    }

}
